package com.yc.cloud.openai.portal.service.impl;

import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.Map;

import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.yc.cloud.common.basic.exception.Asserts;
import com.yc.cloud.common.basic.utils.PathUtils;
import com.yc.cloud.common.oss.service.OssFileService;
import com.yc.cloud.openai.entity.VideoRecord;
import com.yc.cloud.openai.portal.common.PortalErrorTips;
import com.yc.cloud.openai.portal.dao.TextToVideoClient;
import com.yc.cloud.openai.portal.dao.VideoClient;
import com.yc.cloud.openai.portal.dto.PromptDto;
import com.yc.cloud.openai.portal.dto.request.TextToVideoRequest;
import com.yc.cloud.openai.portal.dto.video.request.ImageToVideoRequest;
import com.yc.cloud.openai.portal.enums.PromptType;
import com.yc.cloud.openai.portal.enums.TextToVideoProvider;
import com.yc.cloud.openai.portal.enums.VideoPromptType;
import com.yc.cloud.openai.portal.enums.VideoProvider;
import com.yc.cloud.openai.portal.factory.TextToVideoClientFactory;
import com.yc.cloud.openai.portal.factory.VideoClientFactory;
import com.yc.cloud.openai.portal.service.VideoRecordService;
import com.yc.cloud.openai.portal.service.VideoService;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;
import lombok.val;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
public class VideoServiceImpl implements VideoService {

    private final Map<TextToVideoProvider, TextToVideoClient> textToVideoClientMap;
    private final VideoRecordService videoRecordService;
    private final Map<VideoProvider, VideoClient> videoClientMap;
    private final PathUtils pathUtils;
    private final OssFileService ossFileService;

    public VideoServiceImpl(TextToVideoClientFactory clientFactory, VideoRecordService videoRecordService,
            VideoClientFactory videoClientFactory, PathUtils pathUtils, OssFileService ossFileService) {
        this.textToVideoClientMap = clientFactory.getClientMap();
        this.videoRecordService = videoRecordService;
        this.videoClientMap = videoClientFactory.getClientMap();
        this.pathUtils = pathUtils;
        this.ossFileService = ossFileService;
    }

    @Override
    public PromptDto textToVideo(TextToVideoRequest param) {
        TextToVideoClient client = textToVideoClientMap.get(param.getProvider());
        if (client == null) {
            Asserts.fail(PortalErrorTips.UNSUPPORTED_PROVIDER);
            return null;
        }
        TextToVideoRequest request = new TextToVideoRequest();
        request.setPrompt(param.getPrompt());
        request.setClientId(param.getClientId());
        request.setProvider(param.getProvider());
        val textToVideoResponse = client.convertTextToVideo(request);
        if (textToVideoResponse != null && StrUtil.isNotEmpty(textToVideoResponse.getPromptId())) {
            // 保存文生图的一些信息到数据库中,便于后续查询
            val saveFlag = generateVideoRecord(param.getProvider().getKey(), param.getPrompt(),
                    PromptType.TEXT2VIDEO.getKey(), textToVideoResponse, null);
            if (!saveFlag) {
                log.error(PortalErrorTips.VIDEO_RECORD_SAVE_FAILED);
            }
        }
        return textToVideoResponse;
    }



    @Override
    @SneakyThrows
    public PromptDto imageToVideo(ImageToVideoRequest param, MultipartFile multipartFile) {
        VideoClient client = videoClientMap.get(param.getProvider());
        if (client == null) {
            Asserts.fail(PortalErrorTips.PROVIDER_NOT_FOUND);
            return null;
        }
        // multipartfile 转file,保存到磁盘上,按照clientId创建文件夹
        val newFileName = System.currentTimeMillis() + "." +
                FileUtil.getSuffix(multipartFile.getOriginalFilename());
        val path = Paths.get(pathUtils.getBasePath(), param.getClientId(),
                newFileName);
        val file = FileUtil.writeBytes(multipartFile.getBytes(), path.toFile());
        val promptDto = client.convertImageVideo(param, file);
        if (StrUtil.isNotEmpty(promptDto.getPromptId())) {
            // 构建ossfile 和 modelrecord
            val ossFile = ossFileService.saveOssFile(path.toString());
            var sampleFileId = "";
            if (ossFile != null) {
                // 上传的参考图文件ID
                sampleFileId = ossFile.getFileId();
            }
            generateVideoRecord(param.getProvider().getKey(), param.getPrompt(), PromptType.IMAGE2VIDEO.getKey(),
                    promptDto, sampleFileId);
        }
        return promptDto;
    }

    // 生成图片转视频的记录

    private boolean generateVideoRecord(String provider, String prompt, String type, PromptDto promptDto,
            String sampleFileId) {
        val videoRecord = new VideoRecord();
        // 客户端ID
        videoRecord.setClientId(promptDto.getClientId());
        // 参考图文件ID
        videoRecord.setSampleFileId(sampleFileId);
        // 提示词内容
        // imageRecord.setPrompt(imageToModelRequest.getPrompt());
        // 设置任务ID
        videoRecord.setUuid(promptDto.getPromptId());
        // 设置生成图片的类型为文生图枚举值
        videoRecord.setType(type);
        videoRecord.setCreateTime(LocalDateTime.now());
        videoRecord.setProvider(provider);
        videoRecord.setPrompt(prompt);
        return videoRecordService.save(videoRecord);
    }
}
